#include "Channel.h"
#include "EventLoop.h"
#include "Logger.h"
#include <sys/epoll.h>

const int Channel::KNoneEvent = 0;
const int Channel::KReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::KWriteEvent = EPOLLOUT;

Channel::Channel(EventLoop *loop, int fd) 
    : loop_(loop)
    , fd_(fd) 
    , events_(0) 
    , revents_(0)
    , index_(-1) 
    , tied_(false) {}


Channel::~Channel() {}


//tie方法调用时机：
void Channel::tie(const std::shared_ptr<void> &obj) { tie_ = obj; tied_ = true; } 
// tie_是弱智能指针，它观察obj管理的资源


/*
当改变channel所表示的events后，update负责在poller中更改fd相应的事件，即调用epoll_ctl
*/
void Channel::update() {

    loop_->updateChannel(this); // this是Channel对象
}

// 在channel所属的eventloop中，把当前channel删除
void Channel::remove() //删除channel
{
    loop_->removeChannel(this);
}

// fd得到poller通知后，处理事件的，调用相应的回调方法
void Channel::handleEvent(Timestamp receiveTime) {
    std::shared_ptr<void> guard;
    if (tied_) {
        guard = tie_.lock();
        if (guard) {
            handleEventWithGuard(receiveTime);
        }
    }
    else {
        handleEventWithGuard(receiveTime);
    }
}

void Channel::handleEventWithGuard(Timestamp receiveTime) {

    LOG_INFO("channel handleEvent revents:%d\n", revents_);

    if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)) { // 发生异常 EPOLLHUP:表示对应的文件描述符被挂断
        if (closeCallback_) {
            closeCallback_();
        }
    }

    if (revents_ & EPOLLERR) {
        if (errorCallback_) {
            errorCallback_();
        }
    }

    if (revents_ & (EPOLLIN | EPOLLPRI)) { //EPOLLPRI:表示对应的文件描述符有紧急的数据可读
        if (readCallback_) {
            readCallback_(receiveTime);
        }
    }

    if (revents_ & EPOLLOUT) {
        if (writeCallback_) {
            writeCallback_();
        }
    }

}

